package com.gitee.generator.universal.common.jsonconfig;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson.serializer.SerializerFeature;
import lombok.extern.slf4j.Slf4j;

import java.lang.reflect.Type;
import java.util.Arrays;
import java.util.List;
import java.util.Map;

/**
 * CreateByFastJson
 * fastJson实现
 * @since 2020-08-20 14:59
 * @author wangshixiu
 */
@Slf4j
public class CreateByFastJson extends JsonConfig {
    /***/
    CreateByFastJson() {
        super();
    }

    /**
     * 加载配置对象缓存，查找配置文件中的el表达式，进行深度自替换
     * @param fileName fileName
     */
    @Override
    protected synchronized void reloadCacheInstance(String fileName) {
        JSONObject jsonObject = JSON.parseObject(JsonConfig.Util.readResourceFileContent(fileName));
        JSONArray includes = jsonObject.getJSONArray(INCLUDES);
        if(null!=includes && !includes.isEmpty()){
            for(int i=0;i<includes.size();i++){
                JSONObject childConfig = JSON.parseObject(JsonConfig.Util.readResourceFileContent(includes.getString(i)));
                childConfig.forEach((k,v)->jsonObject.merge(k,v,(v1,v2)->{
                    log.info("v1:{},\n v2:{}",v1,v2);
                    if(v1 instanceof Map && v2 instanceof Map){
                        ((Map<?,?>) v1).putAll(((Map)v2));
                        log.debug("Map merge:{}",v1);
                        return v1;
                    }else if(v1 instanceof List && v2 instanceof List){
                        ((List<?>) v1).addAll((List)v2);
                        log.debug("List merge:{}",v1);
                        return v1;
                    }else{
                        log.debug("Cover merge:{}",v2);
                        return v2;
                    }
                }));
            }
        }
        configCatch =jsonObject;
        String jsonStr= JsonConfig.Util.replaceElStr(jsonObject);
        log.debug("reloadCacheInstance:{}", jsonStr);
        configCatch =JSON.parseObject(jsonStr);
    }

    /**
     * 获取基本类型，得到的对象是克隆的对象
     * @param arr 数组参数
     * @param <T> 返回结果类型
     * @return T
     */
    @Override
    protected <T> T getBaseValueInstance(String... arr) {
        if (null == arr || arr.length == 0){
            return null;
        }
        JSON catchNode = null;
        Object catchNodeObj = getConfigCatch();
        if(catchNodeObj instanceof JSONObject){
            catchNode=(JSONObject)catchNodeObj;
        }

        if (null == catchNode){
            return null;
        }

        /*遍历*/
        Object obj = null;
        for (int i=0;i<arr.length;i++) {
            /*判断类型，获取到的最终节点要克隆*/
            obj = nodeToObj(catchNode,obj,arr,i);
            if (obj == null) {
                return null;
            }
            /*最终节点是需要得到的基本类型，不强转成JSON类型*/
            if(i<arr.length-1){
                if(!(obj instanceof JSON)){
                    return null;
                }
                catchNode = (JSON) obj;
            }
        }
        return (T)obj;
    }

    /**
     * 查找node的下级
     * @param catchNode catchNode
     * @param obj obj
     * @param arr arr
     * @param i i
     * @return obj
     */
    private Object nodeToObj(JSON catchNode,Object obj,String[] arr,int i){
        /*判断类型，获取到的最终节点要克隆*/
        if (catchNode instanceof JSONObject) {
            JSONObject jo = ((JSONObject) catchNode);
            if(i==arr.length-1){
                jo = JsonConfig.Util.clone(jo);
            }
            obj = jo.get(arr[i]);
        } else if (catchNode instanceof JSONArray) {
            JSONArray ja=((JSONArray) catchNode);
            if(i==arr.length-1){
                ja = JsonConfig.Util.clone(ja);
            }
            try{
                obj = ja.get(Integer.parseInt(arr[i]));
            }catch (NumberFormatException e){
                throw new NumberFormatException(String.format(ARR_NUM_ERR, Arrays.toString(arr),(i+1)));
            }
        }
        return obj;
    }

    /**
     * 字符串转对象
     * @param jsonStr jsonStr
     * @param type type
     * @param <T> T
     * @return T
     */
    @Override
    protected <T> T parseInstance(String jsonStr,Type type) {
        return JSON.parseObject(jsonStr,type);
    }
    @Override
    protected <T> T parseInstance(String jsonStr) {
        return (T)JSON.parseObject(jsonStr);
    }
    @Override
    protected <T> List<T> parseArrayInstance(String jsonStr, Class<T> clazz) {
        return JSON.parseArray(jsonStr,clazz);
    }
    @Override
    protected <T> T parseArrayInstance(String jsonStr) {
        return (T) JSON.parseArray(jsonStr);
    }
    /**
     * 判断是否为json字符串
     * @param str str
     * @return boolean
     */
    @Override
    protected boolean isJsonInstance(String str){
        boolean result;
        try {
            JSON.parse(str);
            result = true;
        } catch (Exception e) {
            result=false;
        }
        return result;
    }

    /**
     * 对象转字符串
     * @param obj obj
     * @return 字符串
     */
    @Override
    protected String toJsonStrInstance(Object obj) {
        return JSON.toJSONString(obj, SerializerFeature.DisableCircularReferenceDetect);
    }
}